#include "StdAfx.h"
#include "SgCylinder.h"
#include "sgpolygon.h"
#include "sgrotate.h"
#include "sgseparator.h"
#include "sgtranslate.h"
#include <cmath>

const double GR_PI = 3.1415926535897932384626433832795;

CSgCylinder::CSgCylinder(double height = 1.0, double radius = 1.0)
{
	m_height = height;
	m_radius = radius;
	m_cylinder = new CSgComposite();

	m_side_num = 20;

	Create();

}

CSgCylinder::~CSgCylinder(void)
{
}


void CSgCylinder::Create()
{
	
	CSgPtr<CSgMesh> m_sides = new CSgMesh();
	m_sides = Sides();

	CSgPtr<CSgMesh> top = new CSgMesh();
	top = Top();

	CSgPtr<CSgMesh> bottom = new CSgMesh();
	bottom = Bottom();

	m_cylinder->AddChild(m_sides);
	m_cylinder->AddChild(top);
	m_cylinder->AddChild(bottom);
	

	

	

}
void CSgCylinder::Render()
{
	m_cylinder->Render();
}

CSgPtr<CSgMesh> CSgCylinder::Top()
{
	CSgPtr<CSgMesh> top = new CSgMesh();
	for(unsigned j = 0; j<m_side_num;j++)
	{
		// Sets the First Vector
		if( j == 0)
		{
			top->AddVertex(CGrVector(0,m_height,0));
			top->AddNormal(CGrVector(0,1,0));
		}
		double angle = (2*GR_PI)/m_side_num;
		double vertex[] = { m_radius * sin(angle * j), m_height,0+ m_radius * cos(angle * j), 0};

		top->AddVertex( vertex );

		if( j == 0)
			continue;
		
		unsigned tl = j;
		unsigned tr = j+1;

		top->AddTriangleVertex(tl, 0, -1);
		top->AddTriangleVertex(tr, 0, -1);
		top->AddTriangleVertex(0, 0, -1);
	}	
	// Adds the Last Triangle
	top->AddTriangleVertex(m_side_num, 0, -1);
	top->AddTriangleVertex(1, 0, -1);
	top->AddTriangleVertex(0, 0, -1);
	
	return top;
}

CSgPtr<CSgMesh> CSgCylinder::Sides()
{
	CSgPtr<CSgMesh> m_sides = new CSgMesh();
	
	double height_step = m_height/m_side_num;
	unsigned count1 = 0;

	for(double k = 0.0; k<m_height; k+= height_step)
	{	
		double center[] = {0.0, k, 0.0};
		double top_center[] = {0.0, k+height_step , 0.0};
		
		for(unsigned j = 0; j<m_side_num;j++)
		{
			double angle = (2*GR_PI)/m_side_num;
			double top_vertex[] = {top_center[0] + m_radius * sin(angle * j), top_center[1], top_center[2] + m_radius * cos(angle * j), 0};
			double bottom_vertex[] = {center[0] + m_radius * sin(angle * j), center[1], center[2] + m_radius * cos(angle * j), 0};
	
			m_sides->AddVertex( top_vertex );
			m_sides->AddVertex( bottom_vertex );


			if(k == 0.0)
				m_sides->AddNormal(CGrVector(sin(angle *j), 0, cos(angle*j)));

			if( j == 0)
				continue;
			
			unsigned temp= count1*(m_side_num*2);
			unsigned tl = j*2-2;
			unsigned ll = j*2-1;
			unsigned lr = j*2+1;
			unsigned tr = j*2;
			//First triangle of square
			m_sides->AddTriangleVertex(temp+tl, j, -1);
			m_sides->AddTriangleVertex(temp+ll, j, -1);
			m_sides->AddTriangleVertex(temp+lr, j, -1);

			//Second triangle of square
			m_sides->AddTriangleVertex(temp+tl, j, -1);
			m_sides->AddTriangleVertex(temp+lr, j, -1);
			m_sides->AddTriangleVertex(temp+tr, j ,-1);	
		}	
		unsigned temp2 = (count1*m_side_num*2);
		m_sides->AddTriangleVertex(temp2+(m_side_num*2) - 2, m_side_num-1, -1);
		m_sides->AddTriangleVertex(temp2+(m_side_num*2) -1, m_side_num-1, -1);
		m_sides->AddTriangleVertex(temp2+1,m_side_num-1, -1);
		m_sides->AddTriangleVertex(temp2+(m_side_num*2) -2, m_side_num-1, -1);
		m_sides->AddTriangleVertex(temp2+1, m_side_num-1, -1);
		m_sides->AddTriangleVertex(temp2+0, m_side_num-1 ,-1);
		count1++;
	}

	return m_sides;
}

CSgPtr<CSgMesh> CSgCylinder::Bottom()
{
	CSgPtr<CSgMesh> bottom = new CSgMesh();
	for(unsigned j = 0; j<m_side_num;j++)
	{
		// Sets the First Vector
		if( j == 0)
		{
			bottom->AddVertex(CGrVector(0,0,0));
			bottom->AddNormal(CGrVector(0,-1,0));
		}
		double angle = (2*GR_PI)/m_side_num;
		double vertex[] = { m_radius * sin(angle * j), 0.,0+ m_radius * cos(angle * j), 0};

		bottom->AddVertex( vertex );

		if( j == 0)
			continue;
		
		unsigned tl = j;
		unsigned tr = j+1;

		bottom->AddTriangleVertex(0, 0, -1);
		bottom->AddTriangleVertex(tr, 0, -1);
		bottom->AddTriangleVertex(tl, 0, -1);
	}	
	// Adds the Last Triangle
	bottom->AddTriangleVertex(0, 0, -1);
	bottom->AddTriangleVertex(1, 0, -1);
	bottom->AddTriangleVertex(m_side_num, 0, -1);
	
	return bottom;
}